package zdream.control.world;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;

public abstract class MFoeBuff {
	public final MFoe foe;

	public MFoeBuff(MFoe foe) {
		this.foe = Objects.requireNonNull(foe);
	}

	/* ************
	 * Life Cycle *
	 ************ */
	private boolean destroyed = false;
	private final transient List<Consumer<MFoe>> cleans = new ArrayList<>();

	public boolean isDestroyed() {
		return destroyed;
	}

	public void destroy() {
		if (destroyed) {
			throw new IllegalStateException(this + " 已经被删除了");
		}
		destroyed = true;

		for (Consumer<MFoe> clean : cleans) {
			clean.accept(foe);
		}
	}

	public Supplier<Boolean> onClean(Consumer<MFoe> handler) {
		cleans.add(handler);
		return () -> cleans.remove(handler);
	}

	public abstract void init();

	/* ************
	 *  Category  *
	 ************ */
	protected Set<String> tags = new HashSet<>();

	{
		addTag(getCategory());
	}

	/**
	 * 如果对应的 tag 已存在, 会返回 false
	 */
	public boolean addTag(String tag) {
		return tags.add(tag);
	}

	public boolean removeTag(String tag) {
		return tags.remove(tag);
	}

	/**
	 * 每个 Buff 有多个类别, 这里只传第一位的.
	 *
	 * 一个 {@link MFoeBuff} 的主 category 都不应该相同
	 */
	public abstract String getCategory();

	public boolean is(String category) {
		return tags.contains(category);
	}

	public boolean not(String category) {
		return !is(category);
	}

	/* ***********
	 * Delegate  *
	 *********** */

	/**
	 * 在某个 hook 触发的时候调用什么代码.
	 * @return 手动清理掉这个 hook 的方法.
	 *   当然, 这个 hook 也会在 buff 删除之后自动清理掉
	 */
	protected MHookStore.HookHandlerBuilder onHook(MHookType type) {
		return foe.registerHook()
				.withType(type)
				.withCleaner(cleaner -> onClean(any -> cleaner.getAsBoolean()));
	}
}
